package com.mxpio.erp.mes.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.MesEnums;
import com.mxpio.erp.common.mes.entity.ManufactureWorkOrder;
import com.mxpio.erp.common.mes.entity.ManufactureWorkOrderTask;
import com.mxpio.erp.common.mes.entity.ManufactureWorkOrderTaskSn;
import com.mxpio.erp.common.mes.entity.OperateLog;
import com.mxpio.erp.common.mes.pojo.ManufactureWorkOrderVo;
import com.mxpio.erp.common.mes.service.ManufactureWorkOrderService;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.technology.entity.ItemQualityProp;
import com.mxpio.erp.common.technology.entity.WorkCenter;
import com.mxpio.erp.common.technology.entity.WorkShop;
import com.mxpio.erp.common.workshop.entity.ManufactureOrder;
import com.mxpio.erp.common.workshop.entity.ManufactureOrderRoute;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.jpa.query.Order;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
public class ManufactureWorkOrderServiceImpl extends BaseServiceImpl<ManufactureWorkOrder> implements ManufactureWorkOrderService {

    private static final String DEFAULT_DISPATCH_MODE = "1";//派单
    @Override
    @Transactional
    public Result<?> manufactureOrderDispatch(ManufactureWorkOrderVo batchInfoVo) {
        //batchInfoVo.setSnControlNeeded("1");
        String bizNo = batchInfoVo.getBizNo();
        String snControlNeeded = batchInfoVo.getSnControlNeeded();
        ManufactureOrder mo = JpaUtil.linq(ManufactureOrder.class).equal("bizNo", bizNo).findOne();
        if (StringUtils.isNotBlank(mo.getSnControlNeeded())){
            snControlNeeded = mo.getSnControlNeeded();
        }
        if (StringUtils.isBlank(snControlNeeded)){
            return Result.error("未指定订单是否sn管控。");
        }
        if (mo==null){
            return Result.error("未查询到对应的生产订单！请检查请求参数。");
        }


        ItemQualityProp inspectRule = JpaUtil.linq(ItemQualityProp.class).equal("propType", "item").equal("code", mo.getProductItemCode()).findOne();
        if (inspectRule==null){
            //return Result.error("未维护订单产品的成品检验规则，请先维护数据。");
            inspectRule = new ItemQualityProp();
        }


        Criteria order = Criteria.create();
        order.addOrder(new Order("batchOrder",true));
        List<ManufactureWorkOrder> batchInfoList = JpaUtil.linq(ManufactureWorkOrder.class).equal("bizNo", bizNo).where(order).list();
        Integer preInvestNum = 0;//已投产数量
        Integer maxSerialNumber = null;
        if (!batchInfoList.isEmpty()){
            preInvestNum = batchInfoList.stream().mapToInt(ManufactureWorkOrder::getBatchNum).reduce(0, Integer::sum);
            maxSerialNumber = batchInfoList.get(0).getBatchOrder();
        }

        int lastNum = mo.getOrderQuantity().intValue() - preInvestNum ;
        if (lastNum < batchInfoVo.getCurrentNum()) {
            return Result.error("订单数量："+mo.getOrderQuantity().toPlainString()+"，已投产数量："+preInvestNum+"，当前投入量："+batchInfoVo.getCurrentNum()+"超过最大可投数量："+lastNum+"。");
        }
        //首次拆批
        if (preInvestNum==0
                && StringUtils.equals(inspectRule.getFirstInspectNeeded(), CommonEnums.YesNo.YES.getCode())
                && inspectRule.getFirstInspectNum()>batchInfoVo.getCurrentNum()){
            return Result.error("首次下发操作，工单数量不能小于首检数量“"+inspectRule.getFirstInspectNum()+"”。");
        }
        ManufactureWorkOrder batchInfo = new ManufactureWorkOrder();

        batchInfo.setBizNo(bizNo);
        batchInfo.setBatchNum(batchInfoVo.getCurrentNum());
        batchInfo.setMainWorkshop(mo.getMainWorkshop());//取生产订单
        batchInfo.setWorkCenterCode(mo.getWorkCenterCode());

        if (preInvestNum==0){//首次下发
            batchInfo.setFirstInspectNeeded(inspectRule.getFirstInspectNeeded());
            batchInfo.setFirstInspectNum(inspectRule.getFirstInspectNum());
            batchInfo.setFirstInspectType(inspectRule.getFirstInspectType());
        }
        //可能首次下发即全部订单数量的情况
        if (StringUtils.equals(inspectRule.getFinalInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
            int finalInspectNum = inspectRule.getFinalInspectNum();
            int unfinalNum = mo.getOrderQuantity().intValue()-finalInspectNum;
            if (preInvestNum==0){//首次下发
                if (batchInfoVo.getCurrentNum()>unfinalNum){
                    batchInfo.setFinalInspectNum(batchInfoVo.getCurrentNum()-unfinalNum);
                    batchInfo.setFinalInspectNeeded(CommonEnums.YesNo.YES.getCode());
                    batchInfo.setFinalInspectType(inspectRule.getFinalInspectType());
                }
            }else{
                if ((batchInfoVo.getCurrentNum()+preInvestNum)>unfinalNum){
                    batchInfo.setFinalInspectNum(batchInfoVo.getCurrentNum()+preInvestNum-unfinalNum);
                    batchInfo.setFinalInspectNeeded(CommonEnums.YesNo.YES.getCode());
                    batchInfo.setFinalInspectType(inspectRule.getFinalInspectType());
                }
            }
        }else{
            batchInfo.setFinalInspectNeeded(CommonEnums.YesNo.NO.getCode());
        }
        if(maxSerialNumber ==null){
            batchInfo.setBatchOrder(1);
        }else{
            batchInfo.setBatchOrder(maxSerialNumber+1);
        }
        batchInfo.setBatchCode(mo.getBizNo()+"_"+String.format("%04d",batchInfo.getBatchOrder()));
        batchInfo.setBatchStatus(MesEnums.WorkOrderStatus.NEW.getCode());//默认开立状态
        this.save(batchInfo);//保存工单

        if (StringUtils.isBlank(mo.getSnControlNeeded())){
            JpaUtil.linu(ManufactureOrder.class).set("snControlNeeded",batchInfoVo.getSnControlNeeded()).equal("bizNo",mo.getBizNo()).update();
        }
        return Result.OK();
    }

    @Override
    @Transactional(readOnly = true)//关联生产订单已下发数量
    public void handleDispatchNum(List<ManufactureOrder> content) {
        if (CollectionUtil.isNotEmpty(content)){
            for (ManufactureOrder mo:content){
                Criteria criteria = Criteria.create();
                criteria.addCriterion("bizNo", Operator.EQ,mo.getBizNo());
                List<ManufactureWorkOrder> list = this.list(ManufactureWorkOrder.class, criteria);
                if (list.isEmpty()){
                    mo.setPreInvestNum(BigDecimal.ZERO);
                }else{
                    int preInvestNum = list.stream().mapToInt(ManufactureWorkOrder::getBatchNum).reduce(0, Integer::sum);
                    mo.setPreInvestNum(new BigDecimal(preInvestNum));
                }
            }
        }
    }

    @Override
    @Transactional
    public Result<?> release(String batchCode) {
        ManufactureWorkOrder batchInfo = this.getById(ManufactureWorkOrder.class, batchCode);
        if (batchInfo == null) {
            return Result.error("工单不存在");
        }
        if (!StringUtils.equals(batchInfo.getBatchStatus(), MesEnums.WorkOrderStatus.NEW.getCode())){
            return Result.error("仅开立状态允许下达");
        }

        ManufactureOrder mo = JpaUtil.linq(ManufactureOrder.class).equal("bizNo", batchInfo.getBizNo()).findOne();
        //根据工单数量和订单工艺路线，生成具体的sn工序任务
        Item productItem = JpaUtil.linq(Item.class).equal("itemCode", mo.getProductItemCode()).findOne();

        String dispatchMode = DEFAULT_DISPATCH_MODE;//系统默认人工派工模式
        WorkCenter workCenter = JpaUtil.getOne(WorkCenter.class, mo.getWorkCenterCode());
        if (workCenter!=null&&StringUtils.isNotBlank(workCenter.getDispatchMode())){
            dispatchMode = workCenter.getDispatchMode();
        }else{
            WorkShop workShop = JpaUtil.getOne(WorkShop.class, mo.getMainWorkshop());
            if (workShop!=null&&StringUtils.isNotBlank(workShop.getDispatchMode())){
                dispatchMode = workShop.getDispatchMode();
            }
        }

        //查询订单工艺路路线
        Criteria orderRouteCri = Criteria.create();
        orderRouteCri.addOrder(new Order("processOrder",false));
        List<ManufactureOrderRoute> orderRouteList = JpaUtil.linq(ManufactureOrderRoute.class).equal("bizNo", batchInfo.getBizNo()).where(orderRouteCri).list();
        if (orderRouteList.isEmpty()){
            return Result.error("订单工艺路线为空");
        }

        int routeLoopIndex = 0;
        for (ManufactureOrderRoute route:orderRouteList){
            routeLoopIndex++;
            ManufactureWorkOrderTask task = new ManufactureWorkOrderTask();
            task.setTaskStatus(MesEnums.WorkOrderTaskStatus.NEW.getCode());//默认
            task.setBizNo(batchInfo.getBizNo());
            task.setBatchCode(batchInfo.getBatchCode());
            task.setTaskCode(task.getBatchCode()+"_"+String.format("%02d",routeLoopIndex));
            task.setTaskIndex(routeLoopIndex);
            task.setFirstInspectNeeded(batchInfo.getFirstInspectNeeded());
            task.setFirstInspectType(batchInfo.getFirstInspectType());
            task.setFinalInspectNeeded(batchInfo.getFinalInspectNeeded());
            task.setFinalInspectType(batchInfo.getFinalInspectType());

            task.setProcCode(route.getProcessCode());
            task.setProcOrder(route.getProcessOrder());
            task.setProcGroupCode(route.getProcGroupCode());
            task.setProcGroupName(route.getProcGroupName());
            task.setPreparationTime(route.getPreparationTime());
            task.setSinglePieceTime(route.getSinglePieceTime());
            task.setRoutProcId(route.getRoutProcId());
            task.setItemCode(productItem.getItemCode());
            task.setItemName(productItem.getItemName());
            task.setItemSpec(productItem.getItemSpec());
            task.setUnitCode(productItem.getUnitCode());
            task.setTaskNum(batchInfo.getBatchNum());
            task.setDispatchMode(dispatchMode);
            if (StringUtils.equals(dispatchMode,DEFAULT_DISPATCH_MODE)){
                task.setDispatchAllowed(CommonEnums.YesNo.YES.getCode());
            }else{
                task.setDispatchAllowed(CommonEnums.YesNo.NO.getCode());
            }
            task.setMainWorkshop(batchInfo.getMainWorkshop());
            task.setWorkCenterCode(batchInfo.getWorkCenterCode());
            JpaUtil.save(task);
            if (StringUtils.equals(mo.getSnControlNeeded(),CommonEnums.YesNo.YES.getCode())){
                for (int i = 0; i < batchInfo.getBatchNum(); i++) {
                    ManufactureWorkOrderTaskSn taskSn = new ManufactureWorkOrderTaskSn();
                    String taskSnCode = task.getTaskCode()+"_"+String.format("%04d",i+1);
                    taskSn.setTaskSnCode(taskSnCode);
                    taskSn.setSnIndex(i+1);
                    taskSn.setTaskCode(task.getTaskCode());
                    taskSn.setBatchCode(task.getBatchCode());
                    taskSn.setBizNo(task.getBizNo());
                    boolean firstInspectFlag = false;
                    if (StringUtils.equals(batchInfo.getFirstInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
                        if (i<batchInfo.getFirstInspectNum()){
                            firstInspectFlag = true;
                        }
                    }
                    boolean finalInspectFlag = false;
                    if (StringUtils.equals(batchInfo.getFinalInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
                        if (i>=(batchInfo.getBatchNum()-batchInfo.getFinalInspectNum())){
                            finalInspectFlag = true;
                        }
                    }
                    if (firstInspectFlag){
                        taskSn.setFirstInspectNeeded(batchInfo.getFirstInspectNeeded());
                        taskSn.setFirstInspectType(batchInfo.getFirstInspectType());
                    }else if (finalInspectFlag){
                        taskSn.setFinalInspectNeeded(batchInfo.getFinalInspectNeeded());
                        taskSn.setFinalInspectType(batchInfo.getFinalInspectType());
                    }
                    taskSn.setItemCode(task.getItemCode());
                    taskSn.setItemName(task.getItemName());
                    taskSn.setUnitCode(task.getUnitCode());
                    taskSn.setItemSpec(task.getItemSpec());
                    taskSn.setDrawingNo(task.getDrawingNo());
                    taskSn.setProcOrder(task.getProcOrder());
                    taskSn.setProcCode(task.getProcCode());
                    taskSn.setProcGroupCode(task.getProcGroupCode());
                    taskSn.setProcGroupName(task.getProcGroupName());
                    JpaUtil.save(taskSn);
                }
            }
            //回写工单工序任务指针
            if (routeLoopIndex==1){
                batchInfo.setNextProcOrder(route.getProcessOrder());//默认第一个工序的工艺序号
            }
        }
        //更新工单状态
        batchInfo.setBatchStatus(MesEnums.WorkOrderStatus.SEND.getCode());
        this.update(batchInfo);

        OperateLog operateLog = new OperateLog();
        operateLog.setBizNo(batchInfo.getBizNo());
        operateLog.setBatchCode(batchInfo.getBatchCode());
        operateLog.setOperationType("工单下达");
        JpaUtil.save(operateLog);
        return Result.OK();
    }
}

